﻿using System;
using System.Linq;
using System.Windows.Forms;
using BlueDot.Mobile.Core;

namespace NavigationSample
{
    public partial class NavigationView : ViewBase
    {
        #region Fields

        private const string NavigationViewShowingAddress = WellKnownActions.ViewShowing + "/NavigationView";
        private IViewWorkflow activeWorkflow;
        private IWorkflowDirector director;
        private IShell shell;

        #endregion

        #region Events

        public event EventHandler ForwardToNextView;

        #endregion

        #region Constructors

        public NavigationView()
        {
            InitializeComponent();
        }

        [DependencyConstructor]
        public NavigationView(IMobileApplication application)
            : base(application)
        {
            InitializeComponent();
        }

        #endregion

        #region Properties

        [DependencyProperty]
        public IWorkflowDirector Director
        {
            set { director = value; }
        }

        [DependencyProperty]
        public IShell Shell
        {
            set { shell = value; }
        }

        #endregion

        #region public

        [Receiver(NavigationViewShowingAddress)]
        public void NavigationViewShowing(object sender, DataEventArgs<IView> e)
        {
            shell.ResetDisplayPanel();
        }

        [Receiver(WellKnownActions.ViewShown)]
        public void ViewShown(object sender, DataEventArgs<IView> e)
        {
            if (e.Data == this)
            {
                shell.DisplayPanel = displayPanel;
                activeWorkflow = (IViewWorkflow) director.ActiveItemInstance;
                CreateNodes();
                SetFirstNodeActive();
            }

            SetActiveNode(e.Data.Name);
        }

        [Receiver(WellKnownActions.ViewWorkflowActivated)]
        public void WorkflowActivated(object sender, DataEventArgs<IViewWorkflow> e)
        {
            activeWorkflow = (ViewWorkflow) e.Data;
            CreateNodes();
            SetActiveNode(activeWorkflow.ActiveItemInstance.GetType().Name);
        }

        #endregion

        #region private

        private void CreateNodes()
        {
            navTreeView.Nodes.Clear();

            var rootNode = new TreeNode(activeWorkflow.GetType().Name);
            navTreeView.Nodes.Add(rootNode);
            foreach (IMetaWorkflowItem workflowItem in activeWorkflow.WorkflowItems)
            {
                if (workflowItem.Instance != null && workflowItem.Instance != this)
                {
                    var node = new TreeNode(workflowItem.Instance.GetType().Name);
                    node.Name = workflowItem.Instance.GetType().Name;
                    rootNode.Nodes.Add(node);
                }
            }

            rootNode.ExpandAll();
        }

        private TreeNode FindNode(string name)
        {
            if (navTreeView.Nodes.Count > 0)
            {
                TreeNode rootNode = navTreeView.Nodes[0];
                if (rootNode.Name == name)
                {
                    return rootNode;
                }
                else
                {
                    TreeNode workingNode = rootNode;
                    while (workingNode.NextVisibleNode != null)
                    {
                        workingNode = workingNode.NextVisibleNode;
                        if (workingNode.Name == name)
                        {
                            return workingNode;
                        }
                    }
                }
            }
            return null;
        }

        private void OnAfterSelect(object sender, TreeViewEventArgs e)
        {
            IMetaWorkflowItem workflowItem =
                activeWorkflow.WorkflowItems.SingleOrDefault(
                    p => p.Instance != null && p.Instance.GetType().Name == e.Node.Name);

            if (workflowItem != null &&
                workflowItem.Instance != null &&
                activeWorkflow.ActiveItemInstance.GetType().Name != e.Node.Name)
            {
                activeWorkflow.ActivateWorkflowItem(workflowItem.Instance);
            }
        }

        private void OnLoad(object sender, EventArgs e)
        {
            activeWorkflow = (IViewWorkflow) director.ActiveItemInstance;
            CreateNodes();
            SetActiveNode(activeWorkflow.ActiveItemInstance.GetType().Name);
        }

        private void SetActiveNode(string name)
        {
            TreeNode node = FindNode(name);
            if (node != null)
            {
                navTreeView.SelectedNode = node;
            }
        }

        private void SetFirstNodeActive()
        {
            IMetaWorkflowItem activeItem = activeWorkflow.ActiveItem;
            int index = activeWorkflow.WorkflowItems.IndexOf(activeItem);

            var nextNodeName = activeWorkflow.WorkflowItems[index + 1].Type.Name;

            TreeNode node = FindNode(nextNodeName);
            navTreeView.SelectedNode = node;
        }

        #endregion
    }
}